package com.bwie.bargain.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.bwie.bargain.dao.BargainDao;
import com.bwie.bargain.dao.NotesDao;
import com.bwie.bargain.entity.BargainEntity;
import com.bwie.bargain.entity.NotesEntity;
import com.bwie.bargain.feign.GoodsFeign;
import com.bwie.bargain.vo.GoodsVo;
import com.bwie.bargain.vo.IdVo;
import com.bwie.common.utils.R;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bwie.common.utils.PageUtils;
import com.bwie.common.utils.Query;

import com.bwie.bargain.dao.BarorderDao;
import com.bwie.bargain.entity.BarorderEntity;
import com.bwie.bargain.service.BarorderService;
import org.springframework.transaction.annotation.Transactional;


@Service("barorderService")
public class BarorderServiceImpl extends ServiceImpl<BarorderDao, BarorderEntity> implements BarorderService {
    @Autowired
    private RedissonClient client;
    @Autowired
    private BargainDao bargainDao;
    @Autowired
    private NotesDao notesDao;
    @Autowired
    private GoodsFeign goodsFeign;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<BarorderEntity> page = this.page(
                new Query<BarorderEntity>().getPage(params),
                new QueryWrapper<BarorderEntity>()
        );

        return new PageUtils(page);
    }

    //砍价订单生成
    @Override
    @Transactional
    public R ptAdd(Long userId, Long activityId) {
        //判断拼团活动库存是否大于0  大于0说明有库存  解决库存超卖
        RLock myLock = client.getLock("myLock2");
        try {
            myLock.lock();
            //查询缓存中活动库存
            BargainEntity bargainEntity = bargainDao.selectById(activityId);
            if (bargainEntity.getStockCount()>0){
                //超买问题：比如一个用户针对一个活动只能买一个，但是发下下了个好几个订单，相当于超买。
                //数据库里面创建联合唯一索引 ，用户id+活动id
                Integer count = (Integer) redisTemplate.opsForValue().get(userId + "Count" + activityId + "And");//redis查一个用户只能买一次
                if (count!=null&&count>0){
                    return R.error("该商品砍价活动已参与");
                }else{
                    //活动表中的秒杀数量-1
                    int count2=bargainEntity.getStockCount();
                    bargainEntity.setStockCount(bargainEntity.getStockCount()-1);
                    int i = bargainDao.updateById(bargainEntity);
                    redisTemplate.boundHashOps("bid").put("item"+activityId,bargainEntity);//库存放入redis
                    BargainEntity bargain = (BargainEntity) redisTemplate.boundHashOps("bid").get("item" + activityId);

                    // 解决订单超卖
                    // 如果库存的update-1 操作正常，就下单成功
                    if (count2>bargain.getStockCount()){
                        //mq异步添加订单
                        IdVo idVo = new IdVo();
                        idVo.setActivityId(activityId);
                        idVo.setUserId(userId);
                        redisTemplate.opsForValue().set(userId+"Count"+activityId+"And",1,bargainEntity.getEndDate().getTime()-new Date().getTime(), TimeUnit.MILLISECONDS);
                        rabbitTemplate.convertAndSend("miaosha","add.orders2", idVo);
                        return R.ok().put("userId",userId).put("bid",activityId);
                    }else {
                        return R.error("库存不足，拼团失败");
                    }
                }
            }else {
                // 无库存 拼团失败
                return R.error("库存不足，拼团失败");
            }
        } finally {

            myLock.unlock();
        }

    }

    //砍价
    @Override
    public R bargain(Long userId, String id, Long oid) {
        //判断是否砍过价，已经帮好友砍过不能再次帮砍
       int findNotes=notesDao.findNotes(userId,id,oid);
       if (findNotes==0){//等于0的时候说明这个活动这个用户没有帮他砍过价 就可以帮忙砍价
           //添加砍价记录
           NotesEntity notesEntity = new NotesEntity();
           BarorderEntity orderEntity = baseMapper.selectById(oid);//根据订单表中活动id查砍价活动信息
           BargainEntity bgainEntity = bargainDao.selectById(orderEntity.getActivityId());
           notesEntity.setUserId(userId);//登录者的id（砍价人id）
           notesEntity.setGoodsId(orderEntity.getGoodsId());
           notesEntity.setBargainId(oid);
           notesEntity.setNotesUserId(Long.parseLong(id));//被砍价人的id
           //查询notes记录数据库中  根据userid和bid
           int i = notesDao.findCount(Long.parseLong(id), orderEntity.getOid());
           notesEntity.setBargainCount(i+1);//砍价人数+1

           //如果是砍价规则1的话（共 刀砍至低价）
           if (bgainEntity.getRulesflag()==1){
               notesEntity.setBargainFlag(1);//砍价规则为1
               // 砍价的次数+1 次数>5就修改订单至最低价
               if (i<bgainEntity.getRules()){
                   //          砍了多少钱(因为是按照次数砍价的，所以是平均砍的钱)
                   notesEntity.setLastPrice((bgainEntity.getGoodsPrice().subtract(bgainEntity.getLastPrice())).divide(BigDecimal.valueOf(bgainEntity.getRules())));
                   baseMapper.updatelastPrice(oid,bgainEntity.getLastPrice());//修改订单的价钱
                   notesEntity.setCreateDate(new Date());//砍价记录时间

                   notesDao.insert(notesEntity);//添加记录
                   return R.ok("恭喜您帮好友砍了一刀。");
               }else {
                   return R.ok("已经砍至最低价");
               }

               //如果是砍价规则2的话（每刀最多可砍 元）
           }else if (bgainEntity.getRulesflag()==2){
               notesEntity.setBargainFlag(2);//砍价规则为2
               BigDecimal subtract = bgainEntity.getGoodsPrice().subtract(bgainEntity.getLastPrice());//能砍掉的钱
               //根据用户id还有活动id去查已经砍掉的钱的和
               //判断和不为空(根据用户id还有活动id去查砍价数量)
               int ii=baseMapper.selectSumCount(userId,oid);
               BigDecimal d=null;
               if (ii!=0){
                   double v = baseMapper.selectSumPrice(userId, oid);
                   d= BigDecimal.valueOf(v);
               }else {
                   d = BigDecimal.valueOf(0);
               }
               if (subtract.subtract(d).compareTo(BigDecimal.ZERO)>0){ //判断待砍的钱-已经砍的钱>0,说明可以继续砍价
                   double v = bgainEntity.getRules() - Math.random() * (bgainEntity.getRules() - 1);//最大可砍金额-最小可砍金额
                   BigDecimal bigDecimal = BigDecimal.valueOf(v);
                   notesEntity.setLastPrice(bigDecimal);//随机砍的价
                   //修改订单表中的付款金额为 原金额-砍掉的随机价
                   baseMapper.updatePayPrice(oid,orderEntity.getGoodsPrice().subtract(bigDecimal));
                   notesEntity.setCreateDate(new Date());//砍价记录时间
                   notesDao.insert(notesEntity);//添加记录

                   if (baseMapper.selectById(oid).getGoodsPrice().doubleValue()<bgainEntity.getLastPrice().doubleValue()){
                       //如果付款价格<最低的话，修改价格为
                       baseMapper.updatePayPrice(oid,bgainEntity.getLastPrice());//修改订单付款金额为最低价
                       return R.ok("已经砍至最低价");
                   }
                   return R.ok("恭喜您帮好友砍了一刀");
               }else{//判断待砍的钱-已经砍的钱<0,说明已经砍到最低价了
                   baseMapper.updatePayPrice(oid,bgainEntity.getLastPrice());//修改订单付款金额为最低价
                   return R.ok("已经砍至最低价");
               }
           }
           return R.ok();
       }else {
         return   R.error("已经帮该好友砍过价啦！");
       }

    }

    @Override
    public BarorderEntity getByUidAid(Long userId, Long activityId) {

        return baseMapper.selectByUidAid(userId,activityId);
    }

    @Override
    public R updateOder(Map<String, String> params) {
        String tradeNo = params.get("out_trade_no");
        BarorderEntity orderEntity = baseMapper.selectOne(new QueryWrapper<BarorderEntity>().eq("orderno", tradeNo));
        String totalAmount = params.get("total_amount");
        //判断金额
        if (orderEntity.getGoodsPrice().doubleValue()==Double.valueOf(totalAmount)){
            R info = goodsFeign.info(orderEntity.getGoodsId());
            GoodsVo goodsVo = info.getData(new TypeReference<GoodsVo>() {
            });
            //修改商品表中库存
            goodsVo.setGoodsStock(goodsVo.getGoodsStock()-orderEntity.getGoodsCount());
            goodsFeign.update2(goodsVo);

            orderEntity.setPayDate(new Date());//支付时间
            orderEntity.setStatus(1);//订单状态：0新建未支付，1已支付，2已发货，3已收货，4已退款，5已完成
            baseMapper.updateById(orderEntity);
            return R.ok("支付完成");
        }

        return R.error("金额有误");
    }

}